﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Lossage.Net.Protocols.Modbus
{
    public interface IModbusTask
    {
        //返回值：发送帧数据结构，返回帧数据结构
        (ModbusModel receiver, ModbusModel sender) ReadOnce(byte adress, byte command, UInt16 startReg, byte regLen, UInt16[] datas); //(* ModbusModel, * ModbusModel, error)
        //获取接受监听事件，以注册 GetReceiverEvent() * events.EventParam[[] byte]
        event Action<IEnumerable<byte>> ReceiveEvent;
        //获取发送监听事件，以注册 GetSenderEvent() * events.EventParam[[] byte]
        event Action<IEnumerable<byte>> SendEvent;
    }
    public abstract class ModbusAction
    {
        ModbusProtocol sendFrame;

        ModbusProtocol receiveFrame;

        protected ModbusProtocol SendFrame
        {
            get
            {
                if (sendFrame == null) 
                    sendFrame = new ModbusProtocol();
                return sendFrame;
            }
            private set => sendFrame = value;
        }
        protected ModbusProtocol ReceiveFrame {
            get
            {
                if (receiveFrame == null)
                    receiveFrame = new ModbusProtocol();
                return receiveFrame;
            }
            private set => receiveFrame = value; 
        }

        //接口SetWriter之后保存
        //writer* func([] byte) error
        //接口SetReader之后保存
        //reader* func() ([]byte, error)

        protected abstract bool write(IEnumerable<byte> data);
        protected abstract IEnumerable<byte> read();
        public bool ReadOnce(byte addr, byte command, UInt16 regNo, byte regLength)
        {
            this.SendFrame.Addr = addr;
            this.SendFrame.Command = (CommandType)command;
            this.SendFrame.RegNo = regNo;
            this.SendFrame.RegLength = regLength;
            var sendbuffer = this.SendFrame.AnalyzeStruct();
            if (sendbuffer == null)
            {
                return false;
            }
            if (!this.write(sendbuffer))
            {
                return false;
            }
            var receiveBuffer = this.read();
            if (receiveBuffer == null)
            {
                return false;
            }
            this.ReceiveFrame.Addr = this.SendFrame.Addr;
            this.ReceiveFrame.Command = this.SendFrame.Command;
            this.ReceiveFrame.RegLength = this.SendFrame.RegLength;
            this.ReceiveFrame.AnalyzeBytes(receiveBuffer, DirectionType.Receive);
            return true;
        }

        public bool WriteOnce(byte addr, byte command, UInt16 regNo, UInt16[] buffer)
        {
            this.SendFrame.Addr = addr;
            this.SendFrame.Command = (CommandType)command;
            this.SendFrame.RegNo = regNo;
            this.SendFrame.Body = buffer;
            var sendbuffer = this.SendFrame.AnalyzeStruct();
            if (sendbuffer == null)
            {
                return false;

            }
            if (!this.write(sendbuffer))
            {
                return false;
            }
            var receiveBuffer = this.read();
            this.ReceiveFrame.Addr = this.SendFrame.Addr;
            this.ReceiveFrame.Command = this.SendFrame.Command;
            this.ReceiveFrame.RegLength = this.SendFrame.RegLength;
            this.ReceiveFrame.AnalyzeBytes(receiveBuffer, DirectionType.Receive);
            return true;
        }
    }
}
